/**
 * @file arbre.h
 * @brief Fichier d'entête du module arbre
 *
 * @author Rachid Delory, Florian Bernard, Keita Mamdou
 */
#ifndef H_ARBRE_H
#define H_ARBRE_H

/* ********************************************************************* */
/*                                                                       */
/*                       Librairies de l'arbre                           */
/*                                                                       */
/* ********************************************************************* */
#include <stdlib.h>
#include "regroupement.h"
#include "oeuvre.h"
#include "ensemble.h"

/* ********************************************************************* */
/*                                                                       */
/*                        Définitions de types                           */
/*                                                                       */
/* ********************************************************************* */

/**
 * @struct sArbre
 * @brief Structure utilisée pour la gestion des arbres
 *
 * Cette structure est utilisée pour gérer un arbre. Les champs de cette structure doivent être modifiés ou lus par les accesseurs et mutateurs
 */
struct sArbre {
  Regroupement *element; /** Information relatif à un arbre */
  Ensemble *eFeuille; /** Liste des différentes feuilles */
  Ensemble *eArbre; /** Liste des différents sous arbres */
  char maj; /** 1 pour à mettre à jour et 0 sinon */
  char sup; /** 1 pour supprimer et 0 sinon */
};

/**
 * @typedef Arbre
 * @brief Redéfinit la structure sArbre
 */
typedef struct sArbre Arbre;



/* ********************************************************************* */
/*                                                                       */
/*                 Fonctions relatives aux arbres                        */
/*                                                                       */
/* ********************************************************************* */

/**
 * @fn void initArbre(Arbre * arbre, const Regroupement *regroupement);
 * @brief Initialise un arbre avec comme information regroupement
 *
 * @param[in,out] arbre
 * @param regrouepement
 */
void init_Arb(Arbre * arbre, const Regroupement *regroupement) ;

/** 
 * @fn void libere_Arb(Arbre * arbre) ;
 * @brief Libere un arbre
 *
 * @param[in,out] arbre Pointeur sur arbre.
 */
void liberer_Arb(Arbre * arbre) ;

/** 
 * @fn Arbre creer_Arb(const Regroupement * regroupement) ;
 * @brief Crée un arbre avec comme information regroupement
 *
 * @param regroupement pointeur sur les informations de l'arbre 
 */
Arbre * creer_Arb(const Regroupement * regroupement);

/** 
 * @fn void detruire_Arb(Arbre **arbre) ;
 * @brief Supprime un arbre dans le tas
 *
 * @param[in,out] arbre doit être NULL après cette fonction
 */
void detruire_Arb(Arbre **arbre);

/**
 * @fn Regroupement * getInformation(Arbre *arbre) ;
 * @brief Retourne les informations de cette arbre
 *
 * @param arbre
 * @return les informations de l'arbre
 */
Regroupement * getInformation(Arbre *arbre);

/**
 * @fn int estVide(const Arbre * arbe) ;
 * @brief Détermine si un arbre est vide
 *
 * @param arbre Arbre à tester
 * @return 1 si l'arbre est vide et 0 sinon
*/
int estVide_Arb(const Arbre *arbre);

/**
 * @fn ListArbre * recupSousArbre(const Arbre * arbre) ;
 * @brief Récupère les sous répertoires de l'arbre arbre
 *
 * @param arbre
 * @return Une liste d'arbre 
 */
Ensemble * recupSousArbre_Arb(const Arbre * arbre) ;

/**
 * @fn const Arbre * recupSousArbreId(const Arbre * arbre, const unsigned int id) ;
 * @brief Récupère le sous arbre comportant l'id
 *
 * @param arbre
 * @param id représente l'arbre recherché
 * @return l'arbre trouvé, NULL sinon
 */
Arbre * recupSousArbreId_Arb(Arbre *arbre, const unsigned int id) ;

/**
 * @fn ListFeuille * recupFeuille(const Arbre *arbre) ;
 * @brief Récupère toutes les feuilles d'un arbre
 *
 * @param arbre
 * @return Une liste de feuille
 */
Ensemble * recupFeuille_Arb(const Arbre * arbre) ;

/**
 * @fn const Arbre * recupSousFeuilleId(const Arbre * arbre, const unsigned int id) ;
 * @brief Récupère la feuille comportant l'id
 *
 * @param arbre
 * @param id représente la feuille recherchée
 * @return l'arbre trouvé, NULL sinon
 */
Oeuvre * recupSousFeuilleId_Arb(Arbre *arbre, const unsigned int id) ;

/**
 * @fn void vider_Arb(Arbre *arbre) ;
 * @brief vide les ensembles de regroupement et d'oeuvre de l'arbre
 *
 * @param[in,out] arbre
 */
void vider_Arb(Arbre * arbre) ;

/**
 * @fn unsigned int hauteur (const Arbre * arbre) ;
 * @brief Calcul la hauteur maximum d'un arbre
 *
 * @param arbre
 * @return La hauteur de l'arbre
 */
unsigned int hauteur_Arb(const Arbre * arbre) ;

/**
 * @fn void ajoutNoeud_Arb(Arbre *arbre, Arbre *sousArbre);
 * @brief Ajout d'un noeud à l'arbre
 *
 * @param[in,out] Arbre pointeur sur Arbre
 * @param Pointeur sur regroupement
 */
void ajoutNoeud_Arb(Arbre *arbre,Arbre *sousArbre);

/**
 * @fn void ajoutFeuille_Arb(Arbre *arbre, Oeuvre * oeuvre);
 * @brief Ajout d'une feuille à l'arbre
 *
 * @param[in,out] Arbre pointeur sur Arbre
 * @param Pointeur sur oeuvre
 */
void ajoutFeuille_Arb(Arbre *arbre, Oeuvre *oeuvre); 

/**
 * @fn int possedeArbre_Arb(const Arbre *arbre, const Arbre *arbreChr) ;
 * @brief Cherche arbreChr dans les sous arbres de arbre
 *
 * @param arbre est l'arbre dans lequel la recherche est éffectuée
 * @param arbreChr est l'arbre à rechercher
 * @return 1 si l'arbreChr à été trouvée et 0 sinon
 */
int possedeArbre_Arb(const Arbre *arbre, const Arbre *arbreChr) ;

/**
 * @fn void deplacerArbre_Arb(Arbre *arbreDest, Arbre *arbrePrt, Arbre *arbreSrc) ;
 * @brief Deplace l'arbreSrc dans arbreDest. Supprime arbreSrc de arbrePrt
 *
 * @param[in,out] arbreDest est l'arbre de destination
 * @param[in,out] arbrePrt est l'arbre parent, peut être à NULL
 * @param[in,out] arbreSrc est l'arbre à déplacer dans arbreDest
 */
void deplacerArbre_Arb(Arbre *arbreDest, Arbre *arbrePrt, Arbre *arbreSrc) ;

/**
 * @fn void deplacerFeuille_Arb(Arbre *arbreDest, Arbre *arbrePrt, Oeuvre *oeuvre);
 * @brief Deplace l'oeuvre dans arbreDest. Supprime l'oeuvre de arbrePrt
 *
 * @param[in,out] arbreDest est l'arbre de destination
 * @param[in,out] arbrePrt est l'arbre parent, peut être à NULL
 * @param[in,out] oeuvre est l'oeuvre à déplacer dans arbreDest
 */
void deplacerFeuille_Arb(Arbre *arbreDest, Arbre *arbrePrt, Oeuvre *oeuvre);

/**
 * @fn void detruireSousArbre_Arb(Arbre *prt, Arbre *detruit);
 * @brief Supprime le sous arbre de prt
 *
 * @param[in,out] prt est l'arbre contenant detruit (ou bien sur dans ces branches)
 * @param[in,out] detruit est l'arbre à détruire
 */
void detruireSousArbre_Arb(Arbre *prt, Arbre *detruit);

/**
 * @fn void afficher_Arb(const Arbre *arbre, const int nbTab) ;
 * @brief Affiche l'arbre donnée avec les dossiers en premier suivi des fichiers
 *
 * @param arbre est l'arbre à afficher
 * @param nbTab nombre de tabulation
 */
void afficher_Arb(Arbre *arbre, const int nbTab) ;

/**
 * @fn void setMaj_Arb(Arbre *arb, const char b);
 * @brief Set le besoin de faire une mise à jour, ou pas
 * 
 * @param[in,out] ptr
 * @parm b
 */
void setMaj_Arb(Arbre *arbre, const char b);

/**
 * @fn char getMaj_Arb(const Arbre *arbre);
 * @brief Retourne 0 si pas besoin de faire la mise à jour, et 1 sinon
 *
 * @param ptr
 * @return Comme un boolean
 */
char getMaj_Arb(const Arbre *arbre);

/**
 * @fn void setSup_Arb(Arbre *arbre, const char b);
 * @brief Set le besoin de le supprimer, ou pas
 * 
 * @param[in,out] ptr
 * @parm b
 */
void setSup_Arb(Arbre *ptr, const char b);

/**
 * @fn char getSup_Arb(const Arbre *ptr);
 * @brief Retourne 0 si pas besoin de le supprimer, et 1 sinon
 *
 * @param ptr
 * @return Comme un boolean
 */
char getSup_Arb(const Arbre *ptr);

/**
 * @fn void regression_Arb() ;
 * @brief Test le module arbre
 */
void regression_Arb();

#endif
